#ifndef __DH_MATH_H_
#define __DH_MATH_H_



#ifdef RENDER_EXPORTS
	#define EXPORT_API __declspec( dllexport )
#else
	#define EXPORT_API __declspec( dllimport )
#endif



EXPORT_API float dh_math_fast_isqrt( const float& a );




class EXPORT_API dh_vec2f
{
	public:
	
		float x, y;
		
		dh_vec2f();
		~dh_vec2f(){}
		
		dh_vec2f(const float* v);
		dh_vec2f(const dh_vec2f& v);
		dh_vec2f(const float& nx, const float& ny);
		
		const inline void set(const float* v) { x = v[0]; y = v[1]; }
		const inline void set(const dh_vec2f& v) { x = v.x; y = v.y; }
		const inline void set(const float& nx, const float& ny) { x = nx; y = ny; }
		
		const inline void operator*= (const float& s) { x *= s; y *= s; }
		const inline void operator/= (const float& s) { x /= s; y /= s; }
		const inline void operator+= (const dh_vec2f& v) { x += v.x; y += v.y; }
		const inline void operator+= (const float* v) { x += v[0]; y += v[1]; }
		const inline void operator-= (const dh_vec2f& v) { x -= v.x; y -= v.y; }
		const inline void operator-= (const float* v) { x -= v[0]; y -= v[1]; }
		const inline void operator=  (const dh_vec2f& v) { x = v.x; y = v.y; }
		const inline void operator=  (const float* v) { x = v[0]; y = v[1]; }
		const inline bool operator== (const dh_vec2f& v) { return ((x == v.x) && (y == v.y)); }
		const inline bool operator== (const float* v) { return ((x == v[0]) && (y == v[1])); }
		const inline bool operator!= (const dh_vec2f& v) { return !(*this == v); }
		const inline bool operator!= (const float* v) { return !(*this == v); }
		
		
		const inline float getLengthF()
		{
			return 1.0F / ( dh_math_fast_isqrt( x * x + y * y ) );
		}
		
		float getLength();
		
		const inline float dotProd(const dh_vec2f& v)
		{
			return (x * v.x) + (y * v.y);
		}
		
		const inline dh_vec2f getPerpVector()
		{
			return dh_vec2f(-y, x);
		}
		
		const inline void normalize()
		{
			float iLen = 1.0F / getLength();
			x *= iLen;
			y *= iLen;
		}
	
	private:
};


class EXPORT_API dh_vec3f
{
	public:
	
		float x, y, z;
	
		dh_vec3f();
		~dh_vec3f(){}
		
		dh_vec3f(const float* v);
		dh_vec3f(const dh_vec3f& v);
		dh_vec3f(const float& nx, const float& ny, const float& nz);
		
		const inline void set(const float* v) { x = v[0]; y = v[1]; z = v[2]; }
		const inline void set(const dh_vec3f& v) { x = v.x; y = v.y; z = v.z; }
		const inline void set(const float& nx, const float& ny, const float& nz) { x = nx; y = ny; z = nz; }
		
		const inline dh_vec3f operator- () { return dh_vec3f(-x, -y, -z); }
		const inline void operator*= (const float& s) { x *= s; y *= s; z *= s; }
		const inline void operator/= (const float& s) { float inv = 1.0F / s; x *= inv; y *= inv; z *= inv; }
		const inline void operator+= (const dh_vec3f& v) { x += v.x; y += v.y; z += v.z; }
		const inline void operator+= (const float* v) { x += v[0]; y += v[1]; z += v[2]; }
		const inline void operator-= (const dh_vec3f& v) { x -= v.x; y -= v.y; z -= v.z; }
		const inline void operator-= (const float* v) { x -= v[0]; y -= v[1]; z -= v[2]; }
		const inline void operator=  (const dh_vec3f& v) { x = v.x; y = v.y; z = v.z; }
		const inline void operator=  (const float* v) { x = v[0]; y = v[1]; z = v[2]; }
		const inline bool operator== (const dh_vec3f& v) { return ((x == v.x) && (y == v.y) && (z == v.z)); }
		const inline bool operator== (const float* v) { return ((x == v[0]) && (y == v[1]) && (z == v[2])); }
		const inline bool operator!= (const dh_vec3f& v) { return !(*this == v); }
		const inline bool operator!= (const float* v) { return !(*this == v); }
		
		const inline dh_vec3f lerp(const dh_vec3f& op, const float& dv)
		{
			return dh_vec3f(x + dv * (op.x - x), y + dv * (op.y - y), z + dv * (op.z - z));
		}
		
		float getLength();

		const inline float dotProd(const dh_vec3f& v)
		{
			return ((x * v.x) + (y * v.y) + (z * v.z));
		}
		
		const inline void normalize()
		{
			float mag = 1.0F / getLength(); x *= mag; y *= mag; z *= mag;
		}
		
		const inline dh_vec3f crossProd(const dh_vec3f& v)
		{
			return dh_vec3f((y * v.z - z * v.y), (z * v.x - x * v.z), (x * v.y - y * v.x));
		}
		
		const inline dh_vec3f crossProd(const float* v)
		{
			return dh_vec3f((y * v[2] - z * v[1]), (z * v[0] - x * v[2]), (x * v[1] - y * v[0]));
		}
		
		const inline float tripleScalar(const dh_vec3f& v, const dh_vec3f& w)
		{
			return ((y * v.z - z * v.y) * w.x + (z * v.x - x * v.z) * w.y + (x * v.y - y * v.x) * w.z);
		}
		
		const inline void	assignIfLess( const dh_vec3f& v )
		{
			x = ( v.x < x ) ? v.x : x;
			y = ( v.y < y ) ? v.y : y;
			z = ( v.z < z ) ? v.z : z;
		}
		
		const inline void	assignIfGreater( const dh_vec3f& v )
		{
			x = ( v.x > x ) ? v.x : x;
			y = ( v.y > y ) ? v.y : y;
			z = ( v.z > z ) ? v.z : z;
		}
	
	
};

class EXPORT_API dh_vec4f
{
	public:
		
		float x, y, z, w;
		
		dh_vec4f() { x = y = z = w = 0.0F; }
		~dh_vec4f(){}
		
		dh_vec4f(const float* v);
		dh_vec4f(const dh_vec4f& v);
		dh_vec4f(const float& nx, const float& ny, const float& nz, const float& nw);
		
		const inline void set(const float* v) { x = v[0]; y = v[1]; z = v[2]; w = v[3]; }
		const inline void set(const dh_vec4f& v) { x = v.x; y = v.y; z = v.z; w = v.w; }
		const inline void set(const float& nx, const float& ny, const float& nz, const float& nw) { x = nx; y = ny; z = nz; w = nw; }
	
		const inline void operator=  (const dh_vec4f& v) { x = v.x; y = v.y; z = v.z; w = v.w; }
		const inline void operator=  (const float* v) { x = v[0]; y = v[1]; z = v[2]; w = v[3]; }
		
		const inline void operator*= (const float& v) { x *= v; y *= v; z *= v; w *= w; }
	
	
};







#endif